package edu.cmu.ece.ds.droidchat;

import java.math.BigInteger;
import java.util.Arrays;

import android.app.AlertDialog;
import android.app.Dialog;
import android.app.TabActivity;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.IBinder;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.TabHost;
import android.widget.TextView;
import android.widget.Toast;
import edu.cmu.ece.ds.droidchat.NetworkService.LocalBinder;
import edu.cmu.ece.ds.droidchat.message.CreateSessionInvitationMessage;
import edu.cmu.ece.ds.droidchat.model.ChatSessionInfo;
import edu.cmu.ece.ds.droidchat.model.MessageBackgroundColor;
import edu.cmu.ece.ds.droidchat.model.StringConstants;
import edu.cmu.ece.ds.droidchat.model.UserInfo;
import edu.cmu.ece.ds.droidchat.model.UserInfo.Availability;
import edu.cmu.ece.ds.droidchat.util.Toolbox;
import edu.cmu.ece.ds.droidchat.view.LoggedInUserView;
import edu.cmu.ece.ds.droidchat.widget.ActionItem;
import edu.cmu.ece.ds.droidchat.widget.QuickActionList;
import edu.cmu.ece.ds.droidchat.widget.QuickActionList.OnListClickListener;

public class DroidChatTabActivity extends TabActivity {
    private final static String TAG = "DroidChatTabActivity";
    private NetworkService mService;
    private boolean mBound = false;
    private QuickActionList l;
    private ImageButton mStatusButton;

    private ServiceMessageReceiver mReceiver; // the BroadcastReceiver component
    static final int DIALOG_CHAT_INVITATION = 0;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Log.d(TAG, "---onCreate---");

        Intent i = getIntent();

        UserInfo myInfo = Toolbox.getMyInfo();

        if (myInfo == null) {
            System.out.println("myInfo is null");
            String myUsername = i
                    .getStringExtra(StringConstants.EXTRA_USERNAME);
            System.out.println("myUsername = " + myUsername);
            myInfo = new UserInfo(
                    i.getStringExtra(StringConstants.EXTRA_USERNAME),
                    i.getStringExtra(StringConstants.EXTRA_USERNAME));
            myInfo.setStatusMessage("wahahaha");
            myInfo.setMessageBackgroundColor(MessageBackgroundColor.values()[PreferenceManager
                .getDefaultSharedPreferences(this).getInt(
                        StringConstants.PREF_KEY_MY_MESSAGE_BACKGROUND_COLOR,
                        MessageBackgroundColor.AQUA.ordinal())]);
            Toolbox.setMyInfo(myInfo);
        } else {
            System.out.println("myInfo is not null");
        }
        
        setContentView(R.layout.main_tab_host);

        // prepare LoggedInUserView
        LoggedInUserView v = (LoggedInUserView) findViewById(R.id.logged_in_user_view);
        v.setUserInfo(myInfo);
        if (myInfo.getProfilePicture() == null) {
        	Log.e(TAG, "not calling setUserIcon() - download what");
        	Toolbox.imageDownloader.downloadToLoggedInUserInfoView(myInfo, v);
        } else {
        	Log.e(TAG, "calling setUserIcon()");
            v.setUserIcon(myInfo.getProfilePicture());
        }

        // The activity TabHost
        TabHost tabHost = getTabHost();
        // Resusable TabSpec for each tab
        TabHost.TabSpec spec;
        // Reusable Intent for each tab
        Intent intent;

        // Create an Intent to launch an Activity for the tab (to be reused)
        intent = new Intent().setClass(this, NearbyUsersListActivity.class);

        // Initialize a TabSpec for each tab and add it to the TabHost
        spec = tabHost
                .newTabSpec(StringConstants.TAB_SPEC_NEARBY_USERS)
                .setIndicator(
                        buildIndicator(R.layout.tab_indicator_view_2,
                                R.string.nearby_users)).setContent(intent);
        tabHost.addTab(spec);

        // Do the same for the other tabs
        intent = new Intent().setClass(this, ChatSessionsListActivity.class);
        // put this value to ChatSessionsListActivity so that it knows how to handle invitations
        intent.putExtra(StringConstants.EXTRA_IS_INVITED,
                i.getBooleanExtra(StringConstants.EXTRA_IS_INVITED, false));
        spec = tabHost
                .newTabSpec(StringConstants.TAB_SPEC_CHAT_SESSIONS)
                .setIndicator(
                        buildIndicator(R.layout.tab_indicator_view_2,
                                R.string.chat_sessions)).setContent(intent);
        tabHost.addTab(spec);

        intent = new Intent().setClass(this, SettingsActivity.class);
        spec = tabHost
                .newTabSpec(StringConstants.TAB_SPEC_SETTINGS)
                .setIndicator(
                        buildIndicator(R.layout.tab_indicator_view_2,
                                R.string.settings)).setContent(intent);
        tabHost.addTab(spec);

        if (i.getBooleanExtra(StringConstants.EXTRA_IS_INVITED, false)) {
            // started from notification
            getTabHost().setCurrentTabByTag(
                    StringConstants.TAB_SPEC_CHAT_SESSIONS);
        } else {
            // started from other places
            getTabHost().setCurrentTabByTag(
                    StringConstants.TAB_SPEC_NEARBY_USERS);
        }
        prepareStatusButton();

        Log.e(TAG, "registering broadcast receiver");
        mReceiver = new ServiceMessageReceiver();
        IntentFilter filter = new IntentFilter();
        filter.addAction(StringConstants.ACTION_CHAT_INVITATION);
        this.registerReceiver(mReceiver, filter);

    }

    private void prepareStatusButton() {
        // status dot imagebutton
        mStatusButton = (ImageButton) this
                .findViewById(R.id.logged_in_user_status_button);
        l = new QuickActionList(mStatusButton, LinearLayout.VERTICAL);
        
        // 0
        l.addActionItem(new ActionItem(this,
                R.drawable.status_green_dot_transparent,
                R.string.status_available, ActionItem.HORIZONTAL));
        /*l.addActionItem(new ActionItem(this,
                R.drawable.status_orange_dot_transparent, R.string.status_idle,
                ActionItem.HORIZONTAL));*/
        
        // 1
        l.addActionItem(new ActionItem(this,
                R.drawable.status_red_dot_transparent, R.string.status_busy,
                ActionItem.HORIZONTAL));
        l.addSeparator();
        
        /*l.addActionItem(new ActionItem(this,
                R.drawable.status_gray_dot_transparent,
                R.string.status_appear_offline, ActionItem.HORIZONTAL));
        l.addSeparator();*/
        
        // 2
        l.addActionItem(new ActionItem(this, 0, R.string.status_logout,
                ActionItem.HORIZONTAL));
        l.setOnListClickListener(new OnListClickListener() {

            @Override
            public void onQuickActionListClicked(View contentView, int position) {
                UserInfo myInfo = Toolbox.getMyInfo();
                UserInfo.Availability oldAvailability = myInfo.getAvailability();
                switch (position) {
                case 0:
                    // available
                    mStatusButton
                            .setImageResource(R.drawable.status_green_dot_transparent);
                    myInfo.setAvailability(Availability.AVAILABLE);
                    break;
                case 1:
                	// busy
                    mStatusButton
                            .setImageResource(R.drawable.status_red_dot_transparent);
                    myInfo.setAvailability(Availability.BUSY);
                    break;
                case 3:
                	// logout
                    Toast.makeText(DroidChatTabActivity.this,
                            "Logging out", Toast.LENGTH_SHORT).show();
                    if(mBound){
                    	mService.logout();
                    	Intent serverIntent = new Intent(DroidChatTabActivity.this,
                        		LogInActivity.class);
                    	startActivity(serverIntent);
                    	Log.e(TAG, "calling finish()");
                    	finish();
                    	Log.e(TAG, "calling stopService()");
                    	Intent i2 = new Intent(DroidChatTabActivity.this,
                    			NetworkService.class);
                        stopService(i2);
                    }
                    break;
                }

                if(oldAvailability != myInfo.getAvailability()){
                    // broadcast userinfo update to peers and to server.
                }
            }
        });
        mStatusButton.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                l.show();
            }
        });
    }

    public void onPause() {
        super.onPause();
        Log.d(TAG, "---onPause---");
    }

    public void onResume() {
        super.onResume();
        Log.d(TAG, "---onResume---");
    }

    public void onStart() {
        super.onStart();
        Log.d(TAG, "---onStart---");
        Intent i = this.getIntent();
        boolean test = i.getBooleanExtra(StringConstants.EXTRA_IS_INVITED,
                false);
        if (test == true) {
            Log.e(TAG, StringConstants.EXTRA_IS_INVITED + "=" + true);
            String invitorUsername = i
                    .getStringExtra(StringConstants.EXTRA_INVITOR_USERNAME);
            Log.e(TAG, StringConstants.EXTRA_INVITOR_USERNAME + "="
                    + invitorUsername);
            // TODO: create a new ChatWindowActivity with him and send approval
            // response
        } else {
            Log.e(TAG, StringConstants.EXTRA_IS_INVITED + "=" + false);
        }
        Intent i2 = new Intent(this, NetworkService.class);
        Log.d(TAG, "calling startService()");
        startService(i2);
        
        Intent intent = new Intent(this, NetworkService.class);
        Log.d(TAG, "calling bindService()");
        Toolbox.bindService(this, intent, mConnection,
                Context.BIND_AUTO_CREATE, TAG);
    }

    public void onStop() {
        super.onStop();
        Log.d(TAG, "---onStop---");
        Log.d(TAG, "---calling unbindService---");
        Toolbox.unbindService(this, mConnection, TAG);
    }

    public void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "---onDestroy---");
        unregisterReceiver(mReceiver);
        
        Intent i2 = new Intent(this, NetworkService.class);
        Log.d(TAG, "calling stopService()");
        stopService(i2);
    }

    /** Defines callbacks for service binding, passed to bindService() */
    private ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName className, IBinder service) {
            // We've bound to TCPService, cast the IBinder and get TCPService
            // instance
            LocalBinder binder = (LocalBinder) service;
            mService = binder.getService();
            Log.d(TAG, mService.getPackageName());
            mBound = true;
            Log.d(TAG, "We've bound to TCPService");
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            mBound = false;
        }
    };

    public NetworkService getService() {
        return mService;
    }

    /**
     * Build a {@link View} to be used as a tab indicator, setting the requested
     * string resource as its label.
     */
    private View buildIndicator(int indicatorResId, int textResId) {
        final TextView indicator = (TextView) getLayoutInflater().inflate(
                indicatorResId, getTabWidget(), false);
        indicator.setText(textResId);
        return indicator;
    }

    private class ServiceMessageReceiver extends BroadcastReceiver {
        // public static final String TAG = "ServerMessageReceiver";
        public void onReceive(Context context, Intent intent) {
            Log.e(TAG, "onReceive: " + intent);
            
            String logout = intent.getStringExtra("logout");
            if (logout != null) {
            	Intent serverIntent = new Intent(context,
                        		LogInActivity.class);
        		startActivity(serverIntent);
        		finish();
            } else {
            
	            String username = intent
	                    .getStringExtra(StringConstants.EXTRA_INVITOR_USERNAME);
	
	            UserInfo inviter = Toolbox.retrieveUserInfoByUsername(username);
	            
	            String chatSessionID = intent
	                    .getStringExtra(StringConstants.EXTRA_CHAT_SESSION_ID);
		            
	            boolean OneOnOne = intent.getBooleanExtra(
	            		StringConstants.EXTRA_1ON1,
	            		true);
	            
	            String[] existingParticipants = null;
	            int[] existingParticipantsIP = null;
	            
	            Log.e(TAG+" onReceive()", "username=" + username);
	            Log.e(TAG+" onReceive()","chatSessionID=" + chatSessionID);
	            Log.e(TAG+" onReceive()","OneOnOne=" + OneOnOne);
	            
	            if(OneOnOne==false){
	            	existingParticipants = intent.getStringArrayExtra(
	            			StringConstants.EXTRA_EXISTING_PARTICIPANTS);
	            	/*Log.e(TAG+" onReceive()","existingParticipants=" 
	            			+ Arrays.toString(existingParticipants));*/
	            	existingParticipantsIP = intent.getIntArrayExtra(
	            			StringConstants.EXTRA_EXISTING_PARTICIPANTS_IP);
	            	/*Log.e(TAG+" onReceive()","existingParticipantsIP=" 
	            			+ Arrays.toString(existingParticipantsIP));*/
	            }
	            
	            if (inviter != null && chatSessionID != null) {
	                System.out.println("invitor_username" + username);
	                
	                // if I happen to be inviting this guy for 1-on-1 chat by accident
	                //  use the smaller ChatSessionID 
	                
	                Dialog d = onCreateDialog(
	                		DIALOG_CHAT_INVITATION,
	                		inviter,
	                        chatSessionID, 
	                        OneOnOne, 
	                        existingParticipants,
	                        existingParticipantsIP
	                        );
	                d.show();
	            }
            }
        }
    }

    protected Dialog onCreateDialog(int id,
    		UserInfo inviter,
    		String chatSessionID,
    		boolean OneOnOne, 
    		String[] existingParticipants, 
    		int[] existingParticipantsIP) {
        Dialog dialog;
        
        
        
        switch (id) {
        case DIALOG_CHAT_INVITATION:
            AlertDialog.Builder builder = new AlertDialog.Builder(this);
            if (OneOnOne==true) {
            	// what dialog to show when the invitation is for 1-on-1 chat session
            	builder.setMessage(
                    inviter.getUsername()
                            + " has invited you to start a 1-on-1 chat session. Do you want to join")
                    .setCancelable(false)
                    .setPositiveButton(
                            "Yes",
                            new InvitationAcceptDialog(
                            		chatSessionID, inviter,
                            		existingParticipants, existingParticipantsIP,
                                    true))
                    .setNegativeButton(
                            "No",
                            new InvitationAcceptDialog(chatSessionID, inviter,
                            		existingParticipants, existingParticipantsIP,
                                    false));
            } else {
            	// what dialog to show when the invitation is for multi-user chat session
            	builder.setMessage(
                        inviter.getUsername() + " has invited you to join a chat session. " +
                                "current users in the chat sessions are: " +
                                Toolbox.combineName(existingParticipants, inviter.getUsername()) +
                                ". Do you want to join")
                        .setCancelable(false)
                        .setPositiveButton(
                                "Yes",
                                new InvitationAcceptDialog(chatSessionID, inviter,
                                		existingParticipants, existingParticipantsIP,
										true
                                        ))
                        .setNegativeButton(
                                "No",
                                new InvitationAcceptDialog(chatSessionID, inviter,
                                		existingParticipants, existingParticipantsIP,
										false));
            }
            AlertDialog alert = builder.create();
            dialog = alert;
            break;
        default:
            dialog = null;
        }
        return dialog;
    }

    private class InvitationAcceptDialog implements
            DialogInterface.OnClickListener {
        String chatSessionId;
        UserInfo inviter;
        boolean ans;
        String[] existingParticipants;
        int[] existingParticipantsIP;
        
        
        
        public InvitationAcceptDialog(
        		String chatSessionId,
        		UserInfo inviter,
        		String[] existingParticipants,
        		int[] existingParticipantsIP,
                boolean yOrN) {
            this.chatSessionId = chatSessionId;
            this.inviter = inviter;
            this.existingParticipants = existingParticipants;
            this.existingParticipantsIP = existingParticipantsIP;
            
            ans = yOrN;
        }

        public void onClick(DialogInterface dialog, int which) {

            if (ans == true) {
                // if I clicked YES
            	Log.e(TAG+" onClick()", "i'm clicking YES");
            	ChatSessionInfo ch = Toolbox.getChatSession(chatSessionId);
            	
            	if(ch==null){
            		Log.e(TAG+" onClick()", "chat session is null");
            		return;
            	}
            	
            	/*Log.e(TAG+" onClick()", "number of participants = " +
            			ch.numberOfParticipants());*/
            	
            	// add inviter (and all existing participants) into 
            	//  the chat participants here
            	ch.addParticipant(inviter.getUsername(), inviter.getUserIP());
            	
            	int i=0;
            	if(existingParticipants!=null){
            		Log.e(TAG+" onClick()", "existingParticipants not null");
            		
	            	for(String user: existingParticipants){
	            		UserInfo participant = Toolbox.retrieveUserInfoByUsername(user);
	            		
	            		if (participant==null) {
	            			// first add it into the hashtable, set it to non-neighbor
	            			participant = new UserInfo(user, user);
	            			participant.setUserIP(Toolbox.intToIp(existingParticipantsIP[i]));
							participant.setNeighbor(false);
							Resources res = getResources();
							Drawable myImage = res.getDrawable(R.drawable.no_picture);
							participant.setProfilePicture(myImage);
	            			Toolbox.addNewUser(participant);
	            			Log.e(TAG+" onClick()", participant.getUsername() +
	            					", not my neighbor being added");
	            		} else {
	            			Log.e(TAG+" onClick()", participant.getUsername() +
        					", my neighbor being added");
	            		}
	            		// add into ChatSessionInfo the existing participant
            			ch.addParticipant(participant.getUsername(), participant.getUserIP());
            			i++;
            		}
            	}
            	// remove inviter from ChatSessionInfo
            	ch.setInviter(null);
            	
            	mService.respondToChatInvitation(chatSessionId, inviter.getUsername(),
                        true);
            	mService.sendKeepAlive(chatSessionId, false);
                Toolbox.createChatWindowActivity(DroidChatTabActivity.this,false, this.chatSessionId);
            } else {
            	System.out.println("i'm clicking NO " + chatSessionId);
            	ChatSessionInfo ch = Toolbox.getChatSession(chatSessionId);
            	System.out.println("number of participants = " + ch.numberOfParticipants());
            	
            	// can go ahead and remove the chat session
            	//Toolbox.removeChatSession(chatSessionId);
            	Toolbox.removeChatSession(chatSessionId, true);
            	mService.respondToChatInvitation(chatSessionId, inviter.getUsername(), false);
            	//mService.respondToChatInvitationnew(chatSessionId, inviter.getUsername(), false, inviterPubMOD, inviterPubEXP);
            }
        }
    }
}
